package mysql

import (
	"context"
	"github.com/cloudwego/hertz-examples/bizdemo/hertz_gorm/biz/model"
	"github.com/cloudwego/hertz/pkg/common/hlog"
	"math/big"
	"time"
)

// BatchGetFileTaskByUserId 批量获取文件任务
func BatchGetFileTaskByUserId(ctx context.Context, unionId string, cursor, limit int) ([]*model.FileTask, error) {
	var fileTasks []*model.FileTask
	if err := DB.Where("union_id = ?", unionId).Where("id <= ?", cursor).Order("updated_at desc").
		Limit(limit).Find(&fileTasks).Error; err != nil {
		hlog.CtxErrorf(ctx, "BatchGetFileTaskByUserId err:%v", err)
		return nil, err
	}
	return fileTasks, nil
}

// GetFileTasksByCursor 每页数量
func GetFileTasksByCursor(ctx context.Context, unionID string, cursor string, limit int) ([]*model.FileTask, string, error) {
	var tasks []*model.FileTask
	query := DB.WithContext(ctx).Where("union_id = ?", unionID)

	// 游标处理（cursor=0表示第一页）
	if lastTime, lastID, ok := decodeCursor(cursor); ok {
		// 解析游标值（时间戳+ID的组合）
		// 示例游标格式：1698765432100_12345（时间戳_ID）
		// 使用组合排序条件
		query = query.Where("(updated_at < ?) OR (updated_at = ? AND id < ?)",
			lastTime, lastTime, lastID)
	}

	// 按创建时间倒序、ID倒序排序
	err := query.Order("updated_at DESC, id DESC").Limit(limit).Find(&tasks).Error

	// 生成下一个游标
	var nextCursor string
	if len(tasks) > 0 {
		last := tasks[len(tasks)-1]
		// 组合游标值：时间戳_ID（确保唯一性）
		nextCursor = encodeCursor(last.UpdatedAt, last.ID)
	}
	return tasks, nextCursor, err
}

func encodeCursor(t time.Time, id uint64) string {
	bigA := new(big.Int).SetInt64(t.UnixMicro())
	bigB := new(big.Int).SetUint64(id)
	result := new(big.Int).Lsh(bigA, 64)
	result = result.Add(result, bigB)
	return result.String()
}

func decodeCursor(cursor string) (time.Time, uint64, bool) {
	n, ok := new(big.Int).SetString(cursor, 10)
	if !ok {
		return time.Unix(0, 0), 0, false
	}
	mask := new(big.Int).SetUint64(^uint64(0))
	b := new(big.Int).And(n, mask).Uint64()
	a := new(big.Int).Rsh(n, 64).Int64()
	return time.UnixMicro(a), b, true
}

// GetAllFileTaskByStatus 获取所有指定状态的文件任务列表
func GetAllFileTaskByStatus(ctx context.Context, status int8) ([]*model.FileTask, error) {
	var fileTasks []*model.FileTask
	if err := DB.Where("task_status = ?", status).Find(&fileTasks).Order("created_at").Error; err != nil {
		hlog.CtxErrorf(ctx, "GetAllFileTaskByStatus err:%v", err)
		return nil, err
	}
	return fileTasks, nil
}
